package com.sxt.core.context;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.sxt.core.model.BeanDefine;
import com.sxt.core.model.BeanLabel;
import com.sxt.core.utils.FactoryBeanUtil;
import com.sxt.core.utils.PackageScanUtil;
import com.sxt.core.utils.PropInjectUtil;
import com.sxt.test.service.CupService;
import com.sxt.test.service.impl.CupServiceImpl;

/**
 * IOC容器
 * 
 * @author Liushuangxi
 *
 */
public class IocContext {
	

	public IocContext() {
	}

	// 若使用HashMap，则取对象时，会计算 BeanLabel 的hash 值，若hash 值 不一样，则无法取
	private Map<BeanLabel, Object> iocs = new TreeMap<>();
	
	/**
	 * 通过对象名称来获取对象
	 * @param name
	 * 对象名称
	 * @return
	 * iocs里面的对象
	 */
	public Object getBean(String name) {
		return iocs.get(BeanLabel.of(name));
	}
	
	/**
	 * 通过对象接口来获取对象
	 * @param clazz
	 * 对象接口
	 * @return
	 * iocs里面的对象
	 */
	@SuppressWarnings("unchecked")
	public <T> T getBean(Class<T> clazz) {
		return (T) iocs.get(BeanLabel.of(clazz));
	}
	
	/**
	 * 获取所有对象
	 * @return
	 */
	public Map<BeanLabel,Object> getAllObject(){
		return iocs;
	}
	
	/**
	 * 给IOC容器放入对象
	 * @param beanLabel
	 * 对象标签
	 * @param object
	 * 对象
	 */
	public void setBean(BeanLabel beanLabel,Object object) {
		iocs.put(beanLabel, object);
	}
	
	/**
	 * 根据对象名称判断对象是否存在
	 * @param name
	 * 对象名称
	 * @return
	 */
	public boolean exist(String name) {
		return iocs.containsKey(BeanLabel.of(name));
	}
	
	/**
	 * 根据接口判断对象是否存在
	 * @param clazz
	 * 对象接口
	 * @return
	 */
	public boolean exist(Class<?> clazz) {
		return iocs.containsKey(BeanLabel.of(clazz));
	}
	
	/**
	 * 闭环操作
	 * @param packagesName
	 */
	public IocContext(String packagesName) {
		//		 1  包扫描
		List<BeanDefine> beanDefines = PackageScanUtil.packagSanAndGetBeanDefine(packagesName);
		//		 2 创建对象 // Spring BeanFactory = >IOCContext FactoryBean 用来创建对象
		FactoryBeanUtil.createObject(beanDefines, this);
		//		3 注入属性
		PropInjectUtil.injectProps(beanDefines, this);
	}
	
	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) {
		IocContext ioc = new IocContext();
		CupService cupService = new CupServiceImpl();
		BeanLabel beanLabel = BeanLabel.of(CupService.class, "CupServiceImpl");
		ioc.setBean(beanLabel, cupService);
		//通过接口得到CupService对象
		CupService cupService2 = ioc.getBean(CupService.class);
		System.out.println("根据接口得到对象： "+cupService2);
		Object bean = ioc.getBean("CupServiceImpl");
		System.out.println("根据对象名称得到对象： "+bean);
	}
}
